package com.xbongbong.parent.parse.data;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.LinkInfoPojo;
import com.xbongbong.paas.field.LinkedAttrPoJo;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.UnitItemPoJo;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.pojo.vo.LinkResultDataDTO;
import com.xbongbong.paas.pojo.vo.LinkResultDataVO;
import com.xbongbong.paas.service.field.FieldAnalysisHandler;
import com.xbongbong.paas.service.field.FieldAnalysisPoJo;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.ItemUtil;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.help.RelativeProductHelp;
import com.xbongbong.saas.help.SaasFormHelp;
import com.xbongbong.saas.model.impl.ProductModelImpl;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author: wufeng
 * @date: 2018/11/9 15:40
 * @desrcption: tab关联产品列表处理关联产品的问题
 */
@Component
public class FormDataLinkDataLinkProductServiceImpl extends BaseFormDataLinkDataHelp {

    private static  final Logger LOG = LoggerFactory.getLogger(FormDataLinkDataLinkProductServiceImpl.class);

    @Resource
    private RelativeProductHelp relativeProductHelp;
    @Resource
    private LinkDataHelp linkDataHelp;
    @Resource
    private SaasFormHelp saasFormHelp;
    @Resource
    private Map<Integer, FieldAnalysisHandler> fieldAnalysisHandlerMap;

    public void formDataLinkDataShowGet(LinkResultDataDTO linkResultDataDTO, LinkResultDataVO linkResultDataVO) throws XbbException {
        try {
            List<LinkInfoPojo> linkInfoList = ProFormHelp.getLinkInfo(linkResultDataVO.getExplainList());
            if (linkInfoList.isEmpty()) {
                return;
            }
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getSubFormExplainMapByList(linkResultDataVO.getExplainList());
            List<Long> formIdList = new ArrayList<>();
            List<Long> workOrderFormIdList = new ArrayList<>();
            boolean hasProductLinkForm = false;
            for (LinkInfoPojo linkInfoPojo : linkInfoList) {
                if (Objects.equals(linkInfoPojo.getLinkBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                    workOrderFormIdList.add(linkInfoPojo.getLinkFormId());
                } else {
                    if (!hasProductLinkForm && Objects.equals(linkInfoPojo.getLinkBusinessType(), XbbRefTypeEnum.PRODUCT.getCode())) {
                        hasProductLinkForm = true;
                    }
                    formIdList.add(linkInfoPojo.getLinkFormId());
                }
            }
            // 非工单解释
            Map<String, PaasFormExplainEntity> formExplainMap = getExplainMapByFormIdList(formIdList, linkResultDataDTO.getCorpid());
            // 工单解释
            Map<String, WorkOrderExplainEntity> workOrderFormExplainMap = getWorkOrderExplainMapByFormId(workOrderFormIdList, linkResultDataDTO.getCorpid());

            // 获取关联数据字段所需要的数据
            Map<String, PaasFormDataEntityExt> formDataMap = linkDataHelp.getLinkDataOfBusinessType(linkResultDataDTO, linkResultDataVO);
            if (hasProductLinkForm) {
                //fix bug 35218 collect方法兼容key冲突,冲突时暂取第一个
                Map<String, String> unitMap = relativeProductHelp.getBusinessUnitItems(linkResultDataDTO.getCorpid()).stream().collect(Collectors.toMap(item -> Objects.toString(item.getValue(), ""), ItemPoJo::getText,(key1, key2)->key1));
                Map<Long, MultiUnitItemPoJo> groupBaseUnitMap = relativeProductHelp.getGroupBaseUnitMap(linkResultDataDTO.getCorpid());
                linkResultDataDTO.setUnitMap(unitMap);
                linkResultDataDTO.setGroupBaseUnitMap(groupBaseUnitMap);
            }
            Map<String, FieldAttrEntity> linkDataFieldMap = new HashMap<>(linkResultDataVO.getExplainList().size());
            linkResultDataVO.getExplainList().forEach(item->{
                if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), item.getFieldType()) || Objects.equals(FieldTypeEnum.LINK_DATA_MULTI.getType(), item.getFieldType())) {
                    // 由于是tab列表上的关联产品，所以没有子表单，无需走子表单的判断
                    linkDataFieldMap.put(item.getAttr(), item);
                }
            });

            List<PaasFormDataEntityExt> formDataEsList = linkResultDataVO.getFormDataList();
            Map<String, Set<Long>> linkDataMap = new HashMap<>(formDataEsList.size());
            for (PaasFormDataEntityExt item : formDataEsList) {
                JSONObject data = item.getData();
                linkDataFieldMap.forEach((key, value)->{
                    Object id = data.get(key);
                    if (id == null || Objects.equals(id, 0L) || (id instanceof List && ((List<?>) id).isEmpty())) {
                        return;
                    }
                    if (linkDataMap.containsKey(key)) {
                        Set<Long> idIn = linkDataMap.get(key);
                        if (id instanceof List) {
                            idIn.addAll(JSON.parseArray(JSON.toJSONString(id), Long.class));
                        } else {
                            idIn.add(Long.valueOf(Objects.toString(id)));
                        }
                        linkDataMap.put(key, idIn);
                    } else {
                        Set<Long> idIn = new HashSet<>();
                        if (id instanceof List) {
                            idIn.addAll(JSON.parseArray(JSON.toJSONString(id), Long.class));
                        } else {
                            idIn.add(Long.valueOf(Objects.toString(id)));
                        }
                        linkDataMap.put(key, idIn);
                    }
                });
            }
            Map<String, JSONObject> json = getLinkDataValue(linkResultDataDTO, formExplainMap, workOrderFormExplainMap, linkDataMap, explainMap, linkResultDataVO, formDataMap);

            Map<String, String> unitMap = linkResultDataDTO.getUnitMap() == null ? new HashMap<>(1 << 1) : linkResultDataDTO.getUnitMap();

            linkResultDataVO.getFormDataList().forEach(item->{
                JSONObject data = item.getData();
                json.forEach((key, value)->{
                    String[] list = key.split("&");
                    // 关联产品中自定义的关联数据字段
                    FieldAttrEntity fieldAttrEntity = explainMap.get(list[0]);
                    if (Objects.isNull(fieldAttrEntity)) {
                        return;
                    }
                    if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                        // 关联数据多选主键字段回显
                        JSONArray dataIdList = FastJsonHelper.getJsonArrayOrDefault(data, list[0], new JSONArray());
                        List<JSONObject> linkDataMultiValueList = new ArrayList<>();
                        for (Object dataId : dataIdList) {
                            JSONObject object = json.get(list[0]+"&"+dataId);
                            if (object != null) {
                                // 关联产品关联数据多选主键字段回显
                                JSONObject dataObj = new JSONObject();
                                dataObj.put("name", object.getString(fieldAttrEntity.getLinkInfo().getLinkKey()));
                                dataObj.put("id", dataId);
                                dataObj.put("businessType", fieldAttrEntity.getLinkInfo().getLinkBusinessType());
                                dataObj.put("saasMark", fieldAttrEntity.getLinkInfo().getLinkSaasMark());
                                linkDataMultiValueList.add(dataObj);
                            }
                        }
                        if (CollectionUtils.isNotEmpty(linkDataMultiValueList)) {
                            data.put(fieldAttrEntity.getAttr(), linkDataMultiValueList);
                        }
                    } else {
                        JSONObject object = json.get(list[0]+"&"+data.get(list[0]));
                        if (object == null) {
                            return;
                        }
                        if (Objects.nonNull(fieldAttrEntity.getLinkInfo()) && Objects.equals(fieldAttrEntity.getLinkInfo().getLinkBusinessType(), XbbRefTypeEnum.PRODUCT.getCode()) && Objects.equals(fieldAttrEntity.getIsRedundant(), 0)) {
                            // 关联产品下的产品名称系统字段，单位等字段回显
                            // 多单位显示
                            data.putAll(object);
                            // 关联产品关联数据主键字段回显
                            data.put(fieldAttrEntity.getAttr(), object.get(fieldAttrEntity.getLinkInfo().getLinkKey()));
                            String businessUnit = data.getString(SelectProductEnum.UNIT.getAttr());
                            if (BasicConstant.ONE.equals(data.getIntValue(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr()))) {
                                data.put(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr(), 1);
                                Long unitVal = data.getLong(ProductEnum.UNIT.getSaasAttr());
                                Map<Long, MultiUnitItemPoJo> groupBaseUnitMap = linkResultDataDTO.getGroupBaseUnitMap() == null ? new HashMap<>(1 << 1) : linkResultDataDTO.getGroupBaseUnitMap();
                                MultiUnitItemPoJo multiUnitItemPoJo = groupBaseUnitMap.getOrDefault(unitVal, new MultiUnitItemPoJo());
                                List<UnitItemPoJo> unitItemPoJos = multiUnitItemPoJo.getItemDataPoJoList();

                                if (Objects.equals(businessUnit, StringConstant.INVISIBLE_VALUE)) {
                                    data.put(SelectProductEnum.UNIT.getAttr(), null);
                                } else{
                                    data.put(ProductConstant.UNIT_RATE, unitItemPoJos);
                                    data.put(ProductConstant.TRANSFORM_UNIT_RATE, unitItemPoJos);
                                    if (!StringUtil.isDigital(businessUnit) || Long.parseLong(businessUnit) < ProductConstant.MAX_SINGLE_UNIT_VALUE) {
                                        data.put(SelectProductEnum.UNIT.getAttr(), multiUnitItemPoJo.getBaseName());
                                    } else {
                                        data.put(SelectProductEnum.UNIT.getAttr(), unitMap.get(businessUnit));
                                    }
                                }
                            } else {
                                if (Objects.equals(businessUnit, StringConstant.INVISIBLE_VALUE)) {
                                    data.put(SelectProductEnum.UNIT.getAttr(), null);
                                } else if (Objects.nonNull(data.get(SelectProductEnum.UNIT.getAttr())) && (!StringUtil.isDigital(businessUnit) && !ItemUtil.isUUID(businessUnit))) {
                                    data.put(SelectProductEnum.UNIT.getAttr(), businessUnit);
                                } else {
                                    data.put(SelectProductEnum.UNIT.getAttr(), unitMap.get(businessUnit));
                                }
                            }
                        } else {
                            // 关联产品关联数据主键字段回显
                            data.put(fieldAttrEntity.getAttr(), object.get(fieldAttrEntity.getLinkInfo().getLinkKey()));
                        }
                    }

                });
            });

        } catch (Exception e) {
            LOG.error("获取关联数据失败，", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 拼接关联数据的显示字段
     * @param linkResultDataDTO
     * @param formExplainMap
     * @param workOrderFormExplainMap
     * @param linkDataMap
     * @param explainMap
     * @param linkResultDataVO
     * @param formDataMap
     * @return
     * @throws XbbException
     */
    private Map<String, JSONObject> getLinkDataValue( LinkResultDataDTO linkResultDataDTO, Map<String, PaasFormExplainEntity> formExplainMap, Map<String, WorkOrderExplainEntity> workOrderFormExplainMap, Map<String, Set<Long>> linkDataMap, Map<String, FieldAttrEntity> explainMap, LinkResultDataVO linkResultDataVO, Map<String, PaasFormDataEntityExt> formDataMap) throws XbbException{
        String corpid = linkResultDataDTO.getCorpid();
        Map<String, UserEntity> userMap = linkResultDataVO.getUserMap();
        Map<String, DepartmentEntity> departmentMap = linkResultDataVO.getDepartmentMap();
        Map<String, JSONObject> json = new HashMap<>(linkDataMap.size());
        List<FieldAttrEntity> linkFieldList;
        for (Map.Entry<String, Set<Long>> entry : linkDataMap.entrySet()) {
            String attr = entry.getKey();
            List<String> list = ExplainUtil.getAttrByPoint(attr);
            Integer parentFieldType = null;
            if (list.size() == BasicConstant.TWO) {
                FieldAttrEntity parentField = explainMap.get(list.get(0));
                if (Objects.nonNull(parentField)) {
                    parentFieldType = parentField.getFieldType();
                }
            }
            Set<Long> idList = entry.getValue();
            FieldAttrEntity subField = explainMap.get(attr);
            LinkInfoPojo linkInfoPojo = subField.getLinkInfo();
            Long formId = linkInfoPojo.getLinkFormId();
            // 获取关联表的字段解释信息
            Map<String, FieldAttrEntity> linkExplainMap;
            if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), linkInfoPojo.getLinkBusinessType())) {
                WorkOrderExplainEntity workOrderExplainEntity = workOrderFormExplainMap.get(formId.toString());
                linkExplainMap = ExplainUtil.getExplainMap(workOrderExplainEntity.getExplains(), null);
            } else {
                linkExplainMap = ExplainUtil.getExplainMap(formExplainMap.get(formId.toString()).getExplains(), null);
            }
            String linkKey = linkInfoPojo.getLinkKey();
            linkFieldList = new ArrayList<>();
            // 主键字段
            FieldAttrEntity linkKeyField = linkExplainMap.get(linkKey);
            linkFieldList.add(linkKeyField);
            List<LinkedAttrPoJo> linkedShowAttrList = linkInfoPojo.getLinkedShowAttr();
            if (Objects.equals(FieldTypeEnum.SELECT_PRODUCT.getType(), parentFieldType)) {
                linkedShowAttrList.addAll(linkInfoPojo.getLinkedAttr());
            }

            for (FieldAttrEntity attrEntity : linkFieldList) {
                if (Objects.equals(attrEntity.getSaasAttr(), SelectProductEnum.UNIT.getSaasAttr())) {
                    List<ItemPoJo> productItems = relativeProductHelp.getBusinessUnitItems(corpid);
                    attrEntity.setItems(productItems);
                } else if (Objects.equals(attrEntity.getSaasAttr(), ProductEnum.UNIT.getSaasAttr())) {
                    List<ItemPoJo> productItems = saasFormHelp.getProductItems(corpid);
                    attrEntity.setItems(productItems);
                }
            }
            FieldAnalysisPoJo fieldAnalysisPoJo = new FieldAnalysisPoJo(userMap, departmentMap, new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY), new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY), linkInfoPojo.getLinkBusinessType(), true, corpid, linkInfoPojo.getLinkFormId(), linkInfoPojo.getLinkSaasMark(), null);

            for (Long value : idList) {
                String dataKey = String.valueOf(value);
                if (Objects.equals(SaasMarkEnum.SAAS.getCode(), linkInfoPojo.getLinkSaasMark())) {
                    dataKey = linkInfoPojo.getLinkBusinessType() + "_" + value;
                }
                PaasFormDataEntityExt paasFormDataEntityExt = formDataMap.get(dataKey);
                if (Objects.isNull(paasFormDataEntityExt)) {
                    continue;
                }
                JSONObject targetData = paasFormDataEntityExt.getData();
                JSONObject jsonObject = new JSONObject();
                if (CollectionUtils.isNotEmpty(linkedShowAttrList)) {
                    for (LinkedAttrPoJo item : linkedShowAttrList) {
                        // 关联产品的特殊逻辑
                        String key = item.getAttr().split(StringConstant.COMMA)[1];
                        if (!linkExplainMap.containsKey(key)) {
                            continue;
                        }
                        FieldAttrEntity fieldAttrEntity = linkExplainMap.get(key);
                        FieldAnalysisHandler fieldAnalysisHandler = fieldAnalysisHandlerMap.get(fieldAttrEntity.getFieldType());
                        if (Objects.isNull(fieldAnalysisHandler)) {
                            continue;
                        }
                        Object object = fieldAnalysisHandler.getValue(fieldAttrEntity, paasFormDataEntityExt,  paasFormDataEntityExt.getData(), fieldAnalysisPoJo);
                        jsonObject.put(item.getAttr(), object);
                    }
                }
                for (FieldAttrEntity item : linkFieldList) {
                    FieldAnalysisHandler fieldAnalysisHandler = fieldAnalysisHandlerMap.get(item.getFieldType());
                    if (Objects.isNull(fieldAnalysisHandler)) {
                        continue;
                    }
                    Object object = fieldAnalysisHandler.getValue(item, paasFormDataEntityExt,  paasFormDataEntityExt.getData(), fieldAnalysisPoJo);
                    jsonObject.put(item.getAttr(), object);
                }
                if (Objects.equals(linkInfoPojo.getLinkBusinessType(), XbbRefTypeEnum .PRODUCT.getCode())) {
                    JSONObject productJson = ProductModelImpl.setProductAttribute(targetData);
                    jsonObject.putAll(productJson);
                }
                json.put(attr + "&" + paasFormDataEntityExt.getId(), jsonObject);
            }
        }
        return json;
    }
}
